#ifndef DIARY_H
#define DIARY_H
#include "Diary.h"
#include <iomanip>
#include <ostream>
#include <exception>
using namespace std;

Diary::Diary(){
	//Fill diary with days
	int i;
	for(i=SUNDAY;i<NUM_OF_DAYS;++i){
		this->week.push_back(Day((day_t)i));
	}
}

Diary::~Diary(){}

Diary::Diary(const Diary &d):week(d.week.begin(),d.week.end()){
	
	
}

Diary& Diary::operator =(const Diary& d){
	if(this != &d){
		this->week.clear();
		std::copy(d.week.begin(),d.week.end(),this->week.begin());
	}
	return *this;
}

bool Diary::makeAppointment(day_t day, hour startHour, hour endHour, std::string &subject){
	//try to make an appointment in the requested day
	try{
		return week.at(day).makeAppointment(startHour,endHour,subject);
	}catch(out_of_range& exp){
		return false;
	}
	return false;
}

void Diary::removeAppointment(day_t day, hour startHour){
	try{
		week.at(day).removeAppointment(startHour);
	}catch(out_of_range& exp){
		
	}	
}

Appointment* Diary::findAppointment(day_t day, hour startHour) const {
	try{
		return week.at(day).findAppointment(startHour);
	}catch(out_of_range& exp){
		return 0;
	}
}


Appointment* Diary::firstAppointment(day_t day) const{
	try{
		return week.at(day).getFirstAppointment();
	}catch(out_of_range& exp){
		return 0;
	}
}

bool Diary::copyAppointment(day_t fromDay, hour startHour,day_t toDay ,hour newStartHour){
	//copy appointment is just making it in the requested day
	Appointment* app = findAppointment(fromDay,startHour);
	if(app == 0)
		return false;
	return week.at(toDay).makeAppointment(newStartHour,newStartHour + app->getDuration(),app->getSubject());
}

bool Diary::moveAppointment(day_t fromDay, hour startHour, day_t toDay, hour newStartHour){
	try{
		if(fromDay == toDay){
			return week.at(fromDay).moveAppointment(startHour,newStartHour);
		}
		else{
			Appointment* app = week.at(fromDay).findAppointment(startHour);
			if(app == 0) 
				return false;
			if(week.at(toDay).makeAppointment(newStartHour,newStartHour + app->getDuration(),app->getSubject())){
				week.at(fromDay).removeAppointment(startHour);
				return true;
			}			
		}
	}catch(out_of_range& exp){
		return false;
	}
	return false;
}

// IO manipulator for names of days of week
ostream& daysHeader(ostream &cout){
	int width = 11;
	cout << left;
	cout << setw(width) << "Sunday" << setw(width) << "Monday" << setw(width) << "Tuesday" << setw(width) << "Wedenesday" << setw(width) << "Thursday" << setw(width) << "Friday" << setw(width) << "Saturday" << endl;
	cout << setw(width*7) << setfill('-') << "" << setfill(' ') << endl;
	return cout;
}

ostream& operator<<(ostream& os, const Diary& d){
	int width = 11;
	os << daysHeader;
	Diary temp(d);
	vector<Day>::iterator cDay;
	int i=0;
	bool changed = true;
	while (changed){
		changed = false;
		for(cDay = temp.week.begin();cDay != temp.week.end(); ++cDay){
			Appointment* app  = cDay->getFirstAppointment();
			if(app != 0){
				string subj(app->getSubject());
				if(subj.size() > width){
					subj.erase(subj.begin(),subj.begin()+width);
				}
				os << left << setw(width) << subj;
				changed = true;
			}else{
				os << right << setw(width) << "" ;	
			}
		}
		os << right << endl << left;
		for(cDay = temp.week.begin();cDay != temp.week.end(); ++cDay){
			Appointment* app  = cDay->getFirstAppointment();
			if(app != 0){
				os << left << app->getStartTime() << setw(1) << "-" << app->getEndTime();
				changed = true;
				cDay->removeAppointment(app->getStartTime());
			}else{
				os << right << setw(width) << "" ;	
			}
		}
		os << right << endl << left;
		++i;
	}
	return os;
}

#endif